/*
 * Created on Mar 23, 2006
 *
 */
package org.mushroomdb.storedprocedures;

import java.util.HashMap;
import java.util.Map;

import instantj.compile.CompilationFailedException;
import instantj.compile.Compiler;
import instantj.compile.Source;

import org.apache.log4j.Logger;
import org.mushroomdb.service.Service;

/**
 * @author mchiodi
 */
public class StoredProceduresService implements Service {
	private Map procedures;
	private Map compiled;
	private Logger logger;
	
	/**
	 * Constructs the StoredProceduresService.
	 */
	public StoredProceduresService() {
		this.procedures = new HashMap();
		this.compiled = new HashMap();
		this.logger = Logger.getLogger(this.getClass());
	}
	
	/**
	 * 
	 * @param storedProcedure
	 */
	public void addProcedure(StoredProcedure storedProcedure) {
		this.procedures.put(storedProcedure.getName(),storedProcedure);
	}
	
	/**
	 * 
	 * @param storedProcedure
	 * @return
	 */
	public boolean removeProcedure(StoredProcedure storedProcedure) {
		Object object = this.procedures.remove(storedProcedure.getName());
		return object != null;
	}
	
	/**
	 * 
	 * @param name
	 * @return
	 */
	public StoredProcedure getProcedureByName(String name) {
		return (StoredProcedure) this.procedures.get(name);
	}
	
	/**
	 * 
	 * @param storedProcedure
	 */
	public void execute(StoredProcedure storedProcedure) {
		Runnable runnable = (Runnable) this.compiled.get(storedProcedure);
		
		/* Compile */
		if (runnable == null) {
			this.logger.debug("Compiling procedure " + storedProcedure.getName() + ".");
			try {
				Class type = Compiler.compile(new Source(this.getCode(storedProcedure)),true).getType();
				runnable = (Runnable) type.newInstance();
				this.compiled.put(storedProcedure,runnable);
			} catch (CompilationFailedException e) {
				this.logger.error("Error compiling procedure " + storedProcedure.getName() + ".",e);
			} catch (InstantiationException e) {
				this.logger.error("Error compiling procedure " + storedProcedure.getName() + ".",e);
			} catch (IllegalAccessException e) {
				this.logger.error("Error compiling procedure " + storedProcedure.getName() + ".",e);
			}
		}
		
		/* Execute */
		try {
			this.logger.debug("Running procedure " + storedProcedure.getName() + ".");
			runnable.run();
		} catch (Exception e) {
			this.logger.error("Error running procedure " + storedProcedure.getName() + ".",e);
		}
	}
	
	/**
	 * 
	 * @param storedProcedure
	 * @return
	 */
	private String getCode(StoredProcedure storedProcedure) {
		String code = "package org.mushroomdb.storedprocedures;\n\n" + //$NON-NLS-1$
			"public class SPInstance implements Runnable {\n" + //$NON-NLS-1$
				"\tpublic void run() {\n" + //$NON-NLS-1$
					storedProcedure.getCode() +
				"\t}" + //$NON-NLS-1$
			"}"; //$NON-NLS-1$
		return code;
	}
	
	/* (non-Javadoc)
	 * @see org.mushroomdb.service.Service#initialize()
	 */
	public void initialize() {
		// TODO Persistir SPs
	}

}
